#pragma once
#include "channel.hpp"


using openChannelRequestPtr = std::shared_ptr<openChannelRequest>;
using closeChannelRequestPtr = std::shared_ptr<closeChannelRequest>;
class connection        //5个资源+信道的管理
{
public:
    using Ptr = std::shared_ptr<connection>;
    connection(const muduo::net::TcpConnectionPtr& conn, const ProtobufCodecPtr& codec
            , const QueueConsumerManager::Ptr& qcManager, const VirtualHost::Ptr& host, const ThreadPool::Ptr& threadpool)
    :_conn(conn), _codec(codec), _qcManager(qcManager), _host(host), _threadpool(threadpool), _channels(std::make_shared<channelManager>())
    {}
    ~connection() {}

    void openChannel(const openChannelRequestPtr& req)
    {
        int ok = _channels->openChannel(req->cid(), _conn, _codec, _qcManager, _host, _threadpool);
        return basicResponse(req->cid(), req->rid(), ok);
    }
    void closeChannel(const closeChannelRequestPtr& req)
    {
        _channels->closeChannel(req->cid());
        basicResponse(req->cid(), req->rid(), true);
    }
    channel::Ptr getChannel(const std::string& id)      //加一个，不然链接没法拿到信道
    {
        return _channels->getChannel(id);
    }
private:
    void basicResponse(const std::string& cid, const std::string& rid, bool ok)
    {
        basicCommonResponse resp;
        resp.set_cid(cid);
        resp.set_rid(rid);
        resp.set_ok(ok);
        _codec->send(_conn, resp);
    }
private:
    muduo::net::TcpConnectionPtr _conn;          //信道对应的链接    
    ProtobufCodecPtr _codec;                     //解析protobuf协议
    QueueConsumerManager::Ptr _qcManager;        //消费者管理
    VirtualHost::Ptr _host;                      //交换机，队列，绑定的操作
    ThreadPool::Ptr _threadpool;
    channelManager::Ptr _channels;
};

class connectionManager
{
public:
    using Ptr = std::shared_ptr<connectionManager>;
    connectionManager() {}
    void createConnetion(const muduo::net::TcpConnectionPtr& conn, const ProtobufCodecPtr& codec
            , const QueueConsumerManager::Ptr& qcManager, const VirtualHost::Ptr& host, const ThreadPool::Ptr& threadpool)
    {
        std::unique_lock<std::mutex> lock(_mutex);
        auto it = _connections.find(conn);
        if(it != _connections.end())
            return;
        
        connection::Ptr connectionPtr = std::make_shared<connection>(conn, codec, qcManager, host, threadpool);
        _connections.insert({conn, connectionPtr});
    }
    void deleteConnection(const muduo::net::TcpConnectionPtr& conn)
    {
        std::unique_lock<std::mutex> lock(_mutex);
        auto it = _connections.find(conn);
        if(it == _connections.end())
            return;
        _connections.erase(conn);
    }
    connection::Ptr getConnection(const muduo::net::TcpConnectionPtr& conn)
    {
        std::unique_lock<std::mutex> lock(_mutex);
        auto it = _connections.find(conn);
        if(it == _connections.end())
            return connection::Ptr();
        return it->second;
    }
private:
    std::mutex _mutex;
    std::unordered_map<muduo::net::TcpConnectionPtr, connection::Ptr> _connections;
};